package com.srmt.feishu.client.impl.services;

import com.lark.oapi.Client;
import com.lark.oapi.service.docx.v1.model.*;
import com.srmt.document.exception.DocumentNotFoundException;
import com.srmt.document.exception.DocumentOperationException;
import com.srmt.feishu.client.DocxService;
import com.srmt.feishu.client.util.ResponseValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 默认的文档服务实现
 *
 * 委托给飞书SDK客户端，并使用ResponseValidator统一处理响应
 *
 * @author SRMT Development Team
 * @since 2.0.0
 * @version 6.0.0 添加统一响应处理
 */
class DefaultDocxServiceImpl implements DocxService {
    private static final Logger logger = LoggerFactory.getLogger(DefaultDocxServiceImpl.class);

    private final Client client;

    DefaultDocxServiceImpl(Client client) {
        this.client = client;
    }

    @Override
    public Document createDocument(CreateDocumentReq req) throws Exception {
        CreateDocumentResp resp = client.docx().v1().document().create(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "createDocument",
                r -> r.getData().getDocument()
        );
    }

    @Override
    public Document getDocument(GetDocumentReq req) throws Exception {
        GetDocumentResp resp = client.docx().v1().document().get(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "getDocument",
                r -> r.getData().getDocument()
        );
    }

    @Override
    public Block getDocumentBlock(GetDocumentBlockReq req) throws Exception {
        GetDocumentBlockResp resp = client.docx().v1().documentBlock().get(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "getDocumentBlock",
                r -> r.getData().getBlock()
        );
    }

    @Override
    public Block[] listDocumentBlock(ListDocumentBlockReq req) throws Exception {
        ListDocumentBlockResp resp = client.docx().v1().documentBlock().list(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "listDocumentBlock",
                r -> r.getData().getItems()
        );
    }

    @Override
    public List<Block> listAllDocumentBlocks(String documentId) throws Exception {
        logger.debug("开始获取文档 {} 的所有块（自动分页）", documentId);

        List<Block> allBlocks = new ArrayList<>();
        String pageToken = null;
        int pageCount = 0;

        do {
            pageCount++;
            ListDocumentBlockReq.Builder reqBuilder = ListDocumentBlockReq.newBuilder()
                    .documentId(documentId)
                    .pageSize(500)
                    .documentRevisionId(-1);

            if (pageToken != null) {
                reqBuilder.pageToken(pageToken);
            }

            ListDocumentBlockReq req = reqBuilder.build();
            ListDocumentBlockResp resp = client.docx().v1().documentBlock().list(req);
            //  处理错误响应为旧逻辑，保留对特定错误码的检查，为兼容处理 begin
            if (!resp.success()) {
                // Check if the error is due to document not found
                String errorMsg = resp.getMsg();
                if (errorMsg != null && (errorMsg.contains("not found") ||
                        errorMsg.contains("document_not_found") ||
                        errorMsg.contains("invalid document") ||
                        resp.getCode() == 1062071 || // Document not found code
                        resp.getCode() == 102707)) {  // Invalid document ID code
                    throw new DocumentNotFoundException(documentId);
                }
                throw new DocumentOperationException(
                        String.format("列出块失败: %s (错误码: %d)", errorMsg, resp.getCode()));
            }
            //  处理错误响应为旧逻辑，保留对特定错误码的检查，为兼容处理 end
            // 使用 ResponseValidator 验证响应
            Block[] blocks = ResponseValidator.validateAndExtract(
                    resp,
                    "listAllDocumentBlocks",
                    r -> r.getData().getItems()
            );
            if (blocks != null && blocks.length > 0) {
                allBlocks.addAll(Arrays.asList(blocks));
                logger.debug("第 {} 页获取到 {} 个块", pageCount, blocks.length);
            }

            // 获取下一页的 pageToken
            pageToken = resp.getData() != null ? resp.getData().getPageToken() : null;

        } while (pageToken != null && !pageToken.isEmpty());

        logger.info("文档 {} 共获取 {} 个块（分 {} 页）", documentId, allBlocks.size(), pageCount);
        return allBlocks;
    }

    @Override
    public Block patchDocumentBlock(PatchDocumentBlockReq req) throws Exception {
        PatchDocumentBlockResp resp = client.docx().v1().documentBlock().patch(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "patchDocumentBlock",
                r -> r.getData().getBlock()
        );
    }

    @Override
    public CreateDocumentBlockChildrenRespBody createDocumentBlockChildren(CreateDocumentBlockChildrenReq req) throws Exception {
        CreateDocumentBlockChildrenResp resp = client.docx().v1().documentBlockChildren().create(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "createDocumentBlockChildren",
                CreateDocumentBlockChildrenResp::getData
        );
    }

    @Override
    public CreateDocumentBlockDescendantRespBody createDocumentBlockDescendant(CreateDocumentBlockDescendantReq req) throws Exception {
        CreateDocumentBlockDescendantResp resp = client.docx().v1().documentBlockDescendant().create(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "createDocumentBlockDescendant",
                CreateDocumentBlockDescendantResp::getData
        );
    }

    @Override
    public BatchUpdateDocumentBlockRespBody batchUpdateDocumentBlock(BatchUpdateDocumentBlockReq req) throws Exception {
        BatchUpdateDocumentBlockResp resp = client.docx().v1().documentBlock().batchUpdate(req);
        return ResponseValidator.validateAndExtract(
                resp,
                "batchUpdateDocumentBlock",
                BatchUpdateDocumentBlockResp::getData
        );
    }
}
